package com.dy.design_pattern_study.prototype_mode.dome2;

import com.dy.design_pattern_study.utils.Utils;
import lombok.Data;

import java.io.Serializable;

/**
 * 深克隆类
 * @CreateBy zhangdingyi
 * @Date 2023-03-23
 * @Content 简历类，简历可以 clone 且不用新建一个对象
 * 一般在初始化的信息不发生变化的情况下，克隆是最好的办法。这既隐藏了对象创建的细节，又对性能是大大的提高
 * 不用重新初始化对象，而是动态地获得对象运行时的状态
 * -深克隆
 * 这个实质就是 实体类使用引用对象的时候，直接把引用对象给克隆了再拿过来用
 * 对于本体的话，就是直接的 new 一个对象，那这样的话，不就是把创建对象的开销最简化，最省事
 *
 * 难点其实就在于 深浅克隆的区分，其实实现还是蛮简单的
 */
@Data
public class ResumeDeepCopy implements Serializable,Cloneable {

    public static void main(String[] args) throws CloneNotSupportedException {
        testDeepClone();

        //testClone();

    }

    /**
     * 这里是利用大佬写的方法 -对象的导入
     */
    private static void testDeepClone() {
        ResumeDeepCopy resume = new ResumeDeepCopy("张三");
        resume.setPersonalInfo("男", "23");
        resume.setWorkExperience("2023-03-23", "企业外包");

        resume.setCity(new City());
        resume.setCityData("柳州", "广西");

        ResumeDeepCopy resume1 = Utils.clone(resume);
        resume1.setWorkExperience("2022-04-20", "XX企业");
        resume1.setCityData("柳州2", "广西2");

        ResumeDeepCopy resume2 = Utils.clone(resume1);
        resume2.setPersonalInfo("女", "50");

        //以最后一个生效 -说明City是一个引用类型，引用类型的地址不会跟着进行clone
        resume2.setCityData("柳州3", "广西3");

        resume.display();
        resume1.display();
        resume2.display();

        System.out.println("resume Address = " + Utils.getAddress(resume));
        System.out.println("resume1 Address = " + Utils.getAddress(resume1));
        System.out.println("resume2 Address = " + Utils.getAddress(resume2));
    }

    /**
     * 这里是正常的的clone重写
     * @throws CloneNotSupportedException
     */
    private static void testClone() throws CloneNotSupportedException {
        ResumeDeepCopy resume = new ResumeDeepCopy("张三");
        resume.setPersonalInfo("男", "23");
        resume.setWorkExperience("2023-03-23", "企业外包");

        resume.setCity(new City());
        resume.setCityData("柳州", "广西");

        ResumeDeepCopy resume1 = (ResumeDeepCopy) resume.Clone();
        resume1.setWorkExperience("2022-04-20", "XX企业");
        resume1.setCityData("柳州2", "广西2");

        ResumeDeepCopy resume2 = (ResumeDeepCopy) resume1.Clone();
        resume2.setPersonalInfo("女", "50");

        //以最后一个生效 -说明City是一个引用类型，引用类型的地址不会跟着进行clone
        resume2.setCityData("柳州3", "广西3");

        resume.display();
        resume1.display();
        resume2.display();

        System.out.println("resume Address = " + Utils.getAddress(resume));
        System.out.println("resume1 Address = " + Utils.getAddress(resume1));
        System.out.println("resume2 Address = " + Utils.getAddress(resume2));
    }

    private String name;
    private String sex;
    private String age;
    private String timeArea;
    private String company;

    private City city;

    public ResumeDeepCopy(String name) {
        this.name = name;
        city = new City();
    }

    public ResumeDeepCopy(City city) throws CloneNotSupportedException {
        //然而在实际赋值中，city才是主要的clone对象
        this.city = (City) city.Clone();
    }

    public void setPersonalInfo(String sex, String age) {
        this.sex = sex;
        this.age = age;
    }

    public void setWorkExperience(String timeArea, String company) {
        this.timeArea = timeArea;
        this.company = company;
    }

    public void setCityData(String name, String adress) {
        city.setCityName(name);
        city.setCityAddress(adress);
    }

    public void display() {
        System.out.println("----------简历开始----------------");
        System.out.println("name = " + name);
        System.out.println("sex = " + sex);
        System.out.println("age = " + age);
        System.out.println("timeArea = " + timeArea);
        System.out.println("company = " + company);
        System.out.println("CityName = " + city.getCityName());
        System.out.println("CityAddress = " + city.getCityAddress());
        System.out.println("----------简历结束----------------");
    }

    public Object Clone() throws CloneNotSupportedException {
        //这里相当于直接创建一个新的对象，手动的进行clone 操作
        //既然city才是主要的克隆对象，那么这里直接新建一个对象，是否会让人觉clone不够完美，
        //因为还 创建了一个新对象
        ResumeDeepCopy resume = new ResumeDeepCopy(this.city);
        resume.name = this.name;
        resume.sex = this.sex;
        resume.age = this.age;
        resume.timeArea = this.timeArea;
        resume.company = this.company;

        return resume;
    }
}
